package com.axonactive.yolo.service.implement;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.axonactive.yolo.dao.interfaces.UserRepository;
import com.axonactive.yolo.domain.User;
import com.axonactive.yolo.domain.UserEmail;
import com.axonactive.yolo.exception.UserNotFoundException;
import com.axonactive.yolo.service.interfaces.UserEmailService;
import com.axonactive.yolo.service.interfaces.UserService;
import com.axonactive.yolo.util.CONSTANTS;

@Service
public class UserServiceImpl implements UserService {

	private static final Logger LOGGER = Logger
			.getLogger(UserServiceImpl.class);

	@Resource
	private UserRepository userRepository;

	@Autowired
	private UserEmailService userEmailService;

	@Transactional
//	@CacheEvict(value = "listUserCache", allEntries = true)
	public List<User> findAll() {
		return userRepository.findAll();
	}

	@Transactional
	public User create(User userProfile) {
		User createdUserProfile = userProfile;
		createdUserProfile=userRepository.save(createdUserProfile);
		return createdUserProfile;
	}

	@Transactional
//	@Cacheable(value = "listUserCache", key = "#id")
	public User findById(int id) {
		return userRepository.findOne(id);
	}

	@Transactional(rollbackFor = UserNotFoundException.class)
	public void delete(int id) throws UserNotFoundException {
		User deletedUserProfile = userRepository.findOne(id);

		if (deletedUserProfile == null)
			throw new UserNotFoundException("User NotFoundException");

		userRepository.delete(deletedUserProfile);
	}

	@Transactional(rollbackFor = UserNotFoundException.class)
	public User update(User userProfile) throws UserNotFoundException {
		User updatedUserProfile = userRepository.findOne(userProfile.getId());

		if (updatedUserProfile == null)
			throw new UserNotFoundException("update User NotFoundException");

		updatedUserProfile.setPassword(userProfile.getPassword());
		updatedUserProfile.setFirstName(userProfile.getFirstName());
		updatedUserProfile.setLastName(userProfile.getLastName());
		updatedUserProfile.setDateOfBirth(userProfile.getDateOfBirth());
		updatedUserProfile.setGender(userProfile.getGender());
		updatedUserProfile.setPhone(userProfile.getPhone());
		updatedUserProfile.setLoginCount(userProfile.getLoginCount());
		updatedUserProfile.setResetLinkParam(userProfile.getResetLinkParam());
		updatedUserProfile.setCurrency(userProfile.getCurrency());
		updatedUserProfile.setSendViaEmail(userProfile.isSendViaEmail());
		updatedUserProfile.setSendViaSMS(userProfile.isSendViaSMS());
		updatedUserProfile.setTimeStampTask(userProfile.getTimeStampTask());
		updatedUserProfile.setTimeStampSubscription(userProfile
				.getTimeStampSubscription());
		updatedUserProfile.setTimeStampNotification(userProfile
				.getTimeStampNotification());
		userRepository.save(updatedUserProfile);
		return updatedUserProfile;
	}

	public User updatePassword(int userID, String newPassword)
			throws UserNotFoundException {

		User updatedUserProfile = userRepository.findOne(userID);

		if (updatedUserProfile == null)
			throw new UserNotFoundException(
					"update UserProfile NotFoundException");

		updatedUserProfile.setPassword(newPassword);

		userRepository.save(updatedUserProfile);
		return updatedUserProfile;
	}

	public String getPrimaryEmail(int userID) {
		List<UserEmail> emails = userEmailService.findAllEmailByUserId(userID);
		for (UserEmail email : emails)
			if (email.isPrimary())
				return email.getEmail();
		return null;
	}

//	@Cacheable(value = "listStringEmailByUserIdCache", key = "#userId")
	public List<String> findAllEmailByUserIdExceptPrimaryEmail(int userId) {
		List<String> listEmail = new ArrayList<String>();
		List<UserEmail> emails = userEmailService.findAllEmailByUserId(userId);

		for (UserEmail email : emails) {
			if (!email.isPrimary())
				listEmail.add(email.getEmail());
		}
		return listEmail;
	}

	@Override
//	@Cacheable(value = "listUserCache", key = "#userId")
	public List<String> findAllActivatedEmailByUserId(int userId) {
		List<String> listEmail = new ArrayList<String>();
		List<UserEmail> emails = userEmailService.findAllEmailByUserId(userId);

		for (int i = 0; i < emails.size(); i++) {
			if (emails.get(i).isActive() == true && !emails.get(i).isPrimary()) {
				listEmail.add(emails.get(i).getEmail());
			}
		}

		return listEmail;
	}

	@Override
//	@Cacheable(value = "listUserCache", key = "#userId")
	public List<String> findAllNotActivatedEmailByUserId(int userId) {
		List<String> listEmail = new ArrayList<String>();
		List<UserEmail> emails = userEmailService.findAllEmailByUserId(userId);

		for (int i = 0; i < emails.size(); i++) {
			if (emails.get(i).isActive() == false && !emails.get(i).isPrimary()) {
				listEmail.add(emails.get(i).getEmail());
			}
		}

		return listEmail;
	}

	@Override
//	@Cacheable(value = "listUserCache", key = "#userId")
	public String findByPhone(Integer userId) {
		User user = userRepository.findOne(userId);
		if (user == null)
			return "";
		return user.getPhone();
	}

	/**
	 * @param user
	 * @param param
	 * @return
	 */
	@Override
	public boolean setResetPasswordLinkParam(User user, String param) {
		user.setResetLinkParam(param);
		try {
			update(user);
			return true;
		} catch (UserNotFoundException e) {
			LOGGER.error("User Not Found", e);
			return false;
		}
	}

	// Update time stamp
	@Override
	public boolean updateTimeStamp(int userId, String type)
			throws UserNotFoundException {
		String timeStamp = String.valueOf(new Date().getTime());
		User user = null;
		user = findById(userId);
		if (user != null) {
			switch (type) {
			case CONSTANTS.TASK:
				user.setTimeStampTask(timeStamp);
				break;

			case CONSTANTS.SUBSCRIBE:
				user.setTimeStampSubscription(timeStamp);
				break;

			case CONSTANTS.NOTOFICATION:
				user.setTimeStampNotification(timeStamp);
				break;

			default:
				break;
			}
			update(user);
			return true;
		} else {
			return false;
		}
	}
}
